import random
import string
import requests
import time
import warnings
import re
from typing import Optional, Dict, Any, List
from urllib3.exceptions import InsecureRequestWarning

warnings.filterwarnings('ignore', category=InsecureRequestWarning)


class EmailVerifier:
    def __init__(self, admin_auth: Optional[str] = None, api_base_url: Optional[str] = None, domain: Optional[str] = None):
        self.admin_auth = admin_auth
        self.api_base_url = api_base_url
        self.domain = domain
    
    def generate_random_email(self) -> str:
        username_length = random.randint(6, 12)
        username = ''.join(random.choices(string.ascii_lowercase + string.digits, k=username_length))
        return f"{username}{self.domain}"
    
    def extract_verification_code(self, email_content: str) -> Optional[str]:
        patterns = [
            r'[Yy]our verification code is[:\s]+\*?(\d{4,8})\*?',
            r'verification code[:\s]+\*?(\d{4,8})\*?',
            r'code[:\s]+\*?(\d{4,8})\*?',
            r'验证码[:\s]*[：:]\s*(\d{4,8})',
            r'\*(\d{6})\*',
            r'<strong>(\d{4,8})</strong>',
            r'\b(\d{6})\b(?=.*verification|.*code)',
        ]
        
        for pattern in patterns:
            match = re.search(pattern, email_content, re.IGNORECASE | re.DOTALL)
            if match:
                return match.group(1)
        
        six_digit = re.search(r'\b(\d{6})\b', email_content)
        if six_digit:
            return six_digit.group(1)
        
        return None
    
    def fetch_emails(
        self,
        email_address: str,
        limit: int = 5,
        offset: int = 0
    ) -> Optional[List[Dict[str, Any]]]:
        headers = {
            "x-admin-auth": self.admin_auth
        }
        params = {
            "limit": limit,
            "offset": offset,
            "address": email_address
        }
        
        try:
            response = requests.get(self.api_base_url, headers=headers, params=params, verify=False)
            response.raise_for_status()
            data = response.json()
            return data.get("results", [])
        except requests.exceptions.RequestException as e:
            print(f"Error fetching emails: {e}")
            return None
    
    def wait_for_verification_email(
        self,
        email_address: str,
        max_retries: int = 10,
        retry_delay: int = 2,
        target_content: Optional[str] = None,
        extract_code: bool = True
    ) -> Optional[Dict[str, Any]]:

        for attempt in range(max_retries):
            emails = self.fetch_emails(email_address)
            
            if emails:
                for email in emails:
                    raw_content = email.get("raw", "")
                    
                    if target_content and target_content not in raw_content:
                        continue
                    
                    print(f"✓ Found matching email on attempt {attempt + 1}")
                    
                    if extract_code:
                        code = self.extract_verification_code(raw_content)
                        if code:
                            email['verification_code'] = code
                            print(f"✓ Extracted verification code: {code}")
                        else:
                            print("⚠️ Could not extract verification code")
                    
                    return email
                
                if target_content:
                    print(f"Attempt {attempt + 1}: Emails found but none matched target content")
                else:
                    print(f"Attempt {attempt + 1}: No new emails yet")
            else:
                print(f"Attempt {attempt + 1}: No emails found")
            
            if attempt < max_retries - 1:
                time.sleep(retry_delay)
        
        print(f"Failed to find matching email after {max_retries} attempts")
        return None
    
    def get_latest_verification_code(
        self,
        email_address: str,
        max_wait: int = 20,
        retry_delay: int = 2
    ) -> Optional[str]:

        max_retries = max_wait // retry_delay
        email_data = self.wait_for_verification_email(
            email_address,
            max_retries=max_retries,
            retry_delay=retry_delay,
            target_content="verification",
            extract_code=True
        )
        
        if email_data and 'verification_code' in email_data:
            return email_data['verification_code']
        return None